#include "stdafx.hpp"
#include "linux/IoCtlDisc.h"

#ifdef __LINUX__

const unsigned MSF_OFFSET = 150;

CIoCtlDisc::CIoCtlDisc(const char *device)
  : m_pToc(NULL),
    m_track_count(0)
{
  wxInt32 drive = open(device, O_RDONLY | O_NONBLOCK);
  if (drive >= 0)
  {
    struct cdrom_tochdr header;
    if (ioctl(drive, CDROMREADTOCHDR, &header) >= 0)
    {
      unsigned first = header.cdth_trk0;
      unsigned last = header.cdth_trk1;
      m_track_count = last - first + 1;

      m_pToc = new struct cdrom_tocentry[last + 1];
      for (unsigned track = 0; track < m_track_count; ++track)
      {
        m_pToc[track].cdte_track = track + 1;
        m_pToc[track].cdte_format = CDROM_LBA;
        if (ioctl(drive, CDROMREADTOCENTRY, &m_pToc[track]) >= 0)
          m_pToc[track].cdte_addr.lba += MSF_OFFSET;
        else
          fprintf(stderr, "Can not read toc\n");
      }

      m_pToc[m_track_count].cdte_track = CDROM_LEADOUT;
      m_pToc[m_track_count].cdte_format = CDROM_LBA;
      if (ioctl(drive, CDROMREADTOCENTRY, &m_pToc[m_track_count]) >= 0)
        m_pToc[m_track_count].cdte_addr.lba += MSF_OFFSET;
      else
        fprintf(stderr, "Can not read toc for leadout\n");
    }
    else
      fprintf(stderr, "Can not read header\n");

    close(drive);
  }
  else
    fprintf(stderr, "Can not open %s\n", device);
}

CIoCtlDisc::~CIoCtlDisc()
{
  delete m_pToc;
  m_pToc = NULL;
}

unsigned CIoCtlDisc::GetTrackCount() const
{
  return m_track_count;
}

unsigned long CIoCtlDisc::GetStartFrame(unsigned track) const
{
  return m_pToc[track].cdte_addr.lba;
}

unsigned long CIoCtlDisc::GetFrames(unsigned track) const
{
  return m_pToc[track + 1].cdte_addr.lba - m_pToc[track].cdte_addr.lba;
}

#endif	// __LINUX__
